// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2022 Ivan Baidakou

#pragma once

#include "definitions.hpp"
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <initializer_list>
#include <limits>
#include <tuple>
#include <type_traits>

#pragma pack(push)
#pragma pack(1)

namespace rotor_light {

struct ActorBase;
struct SupervisorBase;

struct Message {
  static constexpr MessageTypeId type_id = 0;

  Message() : to{0} {}
  Message(ActorId to_) : to{to_} {}
  Message(const Message &) = delete;
  Message(Message &&) = delete;

  inline virtual MessageTypeId get_type_id() const { return 0; }

private:
  friend struct ActorBase;
  friend struct SupervisorBase;
  ActorId to;
};

namespace traits {

template <size_t... Items>
auto constexpr max =
    [] { return std::max(std::initializer_list<size_t>{Items...}); };

template <typename... Ts> struct MessageStorage {
  static constexpr size_t item_size = max<sizeof(Ts)...>();
  static constexpr size_t item_alignment = max<alignof(Ts)...>();
  using Item = std::aligned_storage_t<item_size, item_alignment>;
};

} // namespace traits

} // namespace rotor_light

#pragma pack(pop)
